package com.gopay.bis.web.controller.wap;

import com.gopay.bis.common.util.IpAddrUtil;
import com.gopay.bis.service.bank.BankIntrChannConfService;
import com.gopay.bis.service.bank.BankIntrChannConfService.OutStlmTranCode;
import com.gopay.bis.service.bank.BankOrderService;
import com.gopay.bis.service.bank.query.BisBankWhiteListMerchantsService;
import com.gopay.bis.service.bank.wap.GoWapBankService;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.nucc.ebank.pay.res.NuccEbankRes;
import com.gopay.common.domain.bis.BaseBisBankConfig;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.bis.RouteMessage;
import com.gopay.common.domain.proccode.ProcCodeInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.bankorder.trade.InitialSpringBeanName;
import com.gopay.common.proccode.DicProcCodeService;
import com.gopay.common.util.RequestUtils;
import com.gopay.remote.bank.WapPayInteractRemoteService;
import com.gopay.remote.bank.autoroute.BankRoute;
import java.util.Enumeration;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

/**
 * 跳转银行Controller
 * 
 * @GoWapBankController.java
 * @author yaobo
 */
@Controller
@Scope("prototype")
public class GoWapBankController {

	private static Logger logger = LoggerFactory.getLogger(GoWapBankController.class);
	private static final String AUTO_ROUTING = "on"; // 银行自动路由开关

	@Resource(name = "goWapBankService")
	private GoWapBankService goWapBankService;

	@Resource(name = "bankIntrChannConfService")
	private BankIntrChannConfService bankIntrChannConfService;

	@Resource(name = "wapPayService")
	private WapPayInteractRemoteService wapPayService;
	
	@Resource(name = "dicProcCodeService")
	private DicProcCodeService dicProcCodeService;
	
	@Resource(name = "bisConfig")
    private Map<String, String> bisConfig;
	
	@Resource(name = "bankRouteService")
    private BankRoute bankRouteService;
	
	@Resource(name = "bankOrderService")
    private BankOrderService bankOrderService;
	
	@Resource(name = "normalBankRouteService")
    private BankRoute normalBankRouteService;
	
	@Resource(name = "bisBankWhiteListMerchantsService")
    private BisBankWhiteListMerchantsService bisBankWhiteListMerchantsService;


	/**
	 * 跳转银行
	 * 
	 * @param request
	 * @param response
	 * @return ModelAndView
	 */
	@RequestMapping(value = "/goWapBank", method = { RequestMethod.POST })
	protected ModelAndView execute(HttpServletRequest request,HttpServletResponse response) {

		logger.info("--------------- GoWapBankController  ---------------");

		// 打印请求参数
		displayRequestParameters(request);

		ModelAndView model = new ModelAndView();

		try {
			
			checkRequest(request);

			// 订单号
			String orderId = request.getParameter("orderId");
			// 银行业务产品
			String bankBusProd = request.getParameter("bankBusProd");
			// B2B交易CMBC为企业客户号,BOCOM为付款账号
            String specialCode = request.getParameter("specialCode");
			BisBankBusinessProd bankBusProdEnum = BisBankBusinessProd.get(bankBusProd);
			// 持卡人IP地址
			String ip = IpAddrUtil.getRemoteRealIpAddr(request);
			// 消息对象
			BaseMessage base = goWapBankService.buildSign(orderId,RequestUtils.getRemoteRealIpAddr(request));
			base.setBankBusProd(bankBusProdEnum);
			base.setCustomerID(specialCode);
			
            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
            // 是否为白名单商户
            boolean isWhite = bisBankWhiteListMerchantsService.isWhiteListMerchant(base.getSpecial2());
            if (AUTO_ROUTING.equals(bisConfig.get("GOPAY.AUTO.ROUTING")) || isWhite) {
                // 增加银行自动路由开关 add by zhengxue
                RouteMessage routeMessage = new RouteMessage();
                routeMessage.setCustId(base.getSpecial2());
                routeMessage.setGopayOrderId(base.getOrderId());
                routeMessage.setBankCode(base.getBank());
                routeMessage.setProdCode(bankBusProd);
                routeMessage.setTransAmt(base.getAmount());

                if (IntTxnCd._00500.value.equals(base.getSpecial4())
                        || BankConstants.GOPAY_CHONGZHI_CUSTID.equals(base.getSpecial2())) {
                    // 充值交易走通用方案
                    bankConfig = normalBankRouteService.getNormalRoute(routeMessage);
                    if (BankConstants.GOPAY_CHONGZHI_CUSTID.equals(base.getSpecial2())
                            && !IntTxnCd._00500.value.equals(base.getSpecial4())) {
                        // 非充值订单获取merId为GFB0000001

                    }
                } else {
                    bankConfig = bankRouteService.getRoute(routeMessage);
                }
                bankOrderService.addBankRouteLog(routeMessage); // 记录银行自动路由日志
            } else {
                // 获取银行接口通道配置信息
                bankConfig = bankIntrChannConfService.findBaseBisBankExtConfig(base.getBankBusProd(), base.getBank());
            }
            
            if (BisBankInterfaceChannel._14.value.equals(bankConfig.getChCode())) {
                // 银行产品空通道
                logger.error(orderId + " GoWapBankController获取银行产品空通道");
                model.setViewName("screen/bank/bank_null_config");
                return model;
            }
			
			// 校验银行业务产品是否支持该通道
			checkBankBussProdAndIntrChan(bankConfig, bankBusProd);
			// 校验通道信息
			checkBankIntrChan(bankConfig, OutStlmTranCode._1000);

			// 平台外部清算机构代码
			String outStlmCd = InitialSpringBeanName.getOutStlmCd(bankConfig.getChCode(), bankBusProd, base.getBank());
			String intrfaceBankCode = bankConfig.getIntrfaceBankCode();
			if (StringUtils.isBlank(intrfaceBankCode)) {
				intrfaceBankCode = base.getBank();
			}
			
			base.setBankIntrChann(BisBankInterfaceChannel.get(bankConfig.getChCode()));
			base.setSpecial(ip);
			base.setOutStlmCd(outStlmCd);
			// 银行报文加密并组装
			Result result = wapPayService.pay(base);

			if (!result.isSuccess()) {// 处理失败
				throw new GopayException(result.getResultCode());
			}

			//如果为网联网关支付,则进行重定向
			if (StringUtils.equals(BankConstants.BANK_LOGO_NUCCPAY,outStlmCd)) {
				NuccEbankRes res = (NuccEbankRes) result.getDefaultModel();
				String rdrctUrl = res.getMsgBody().getBizInf().getRdrctUrl();
				if (StringUtils.isBlank(rdrctUrl)) {
					logger.error("------goBankController nucc return payUrl is blank--------");
					throw new GopayException(ProcCodeConstants.PROC_CODE_100E6130);
				}
				logger.error("------goBankController nucc return payUrl--------"+rdrctUrl);
				model.addObject("nuccBankUrl", rdrctUrl);//网联返回银行跳转地址
			}

			model.addObject("outStlmCd", outStlmCd);// 平台外部清算机构代码
			model.addObject("bankCode", base.getBank());// 接口银行码
			
			model.addObject("message", result.getDefaultModel());// 清算机构消息对象
			model.setViewName(getViewName(bankBusProdEnum));// 页面

		} catch (GopayException e) {
			logger.error("GoBankController GopayException", e);
			ProcCodeInfo procCodeInfo = dicProcCodeService.getProcCodeInfo(e.getErrCode());
			model.addObject("errorCode", e.getErrCode());
			model.addObject("errorMsg", procCodeInfo.getMessage());
			model.setViewName("screen/error");
		} catch (Exception e) {
			logger.error("GoBankController Exception", e);
			model.addObject("errorCode", ProcCodeConstants.PROC_CODE_100F1002);
			model.addObject("errorMsg", e.getMessage());
			model.setViewName("screen/error");
		}
		return model;
	}

	/**
	 * logger
	 * 
	 * @param request
	 */
	@SuppressWarnings("rawtypes")
	private void displayRequestParameters(HttpServletRequest request) {
		for (Enumeration enumeration = request.getParameterNames(); enumeration.hasMoreElements();) {
			String eleName = (String) enumeration.nextElement();
			String eleValue = request.getParameter(eleName);
			logger.info("收到的请求参数键: [" + eleName + "]，值: [" + eleValue + "]");
		}
	}

	/**
	 * 
	 * @param bankBusProdEnum
	 * @return String
	 * @throws com.gopay.common.exception.GopayException
	 */
	private String getViewName(BisBankBusinessProd bankBusProdEnum)throws GopayException {
		if (BisBankBusinessProd._00.equals(bankBusProdEnum)) {
			return "screen/bank/submit_b2c_bank";
		} else if (BisBankBusinessProd._01.equals(bankBusProdEnum)) {
			return "screen/bank/submit_b2b_bank";
		}else if (BisBankBusinessProd._11.equals(bankBusProdEnum)){
			return "screen/wap/bank/submit_wap_b2c_bank";
		}
		logger.error("暂不支持的银行业务产品：" + bankBusProdEnum);
		throw new GopayException(ProcCodeConstants.PROC_CODE_100E7014);
	}


	/**
	 * 校验银行业务产品是否支持该通道
	 * @param config
	 * @param bankBusProd
	 * @throws com.gopay.common.exception.GopayException
	 */
	private void checkBankBussProdAndIntrChan(BaseBisBankExtConfig config,
			String bankBusProd) throws GopayException {
		if(null == config){
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7021);
		}
		String intrChann = config.getChCode();// 接口通道
		bankIntrChannConfService.checkBankBussProdAndIntrChan(intrChann, bankBusProd);
	}

	/**
	 * 校验银行通道信息
	 *
	 * @param config
	 * @param outTranCode
	 * @throws com.gopay.common.exception.GopayException
	 */
	private void checkBankIntrChan(BaseBisBankConfig config,OutStlmTranCode outTranCode) throws GopayException {
		bankIntrChannConfService.checkBankIntrChan(config, outTranCode);
	}

	/**
	 *
	 * @param request
	 * @throws com.gopay.common.exception.GopayException
	 * 
	 */
	private void checkRequest(HttpServletRequest request) throws GopayException{
		String orderId = request.getParameter("orderId");
		String bankBusProd = request.getParameter("bankBusProd");
		logger.error("-----------orderId----------------"+orderId);
		logger.error("-----------bankBusProd----------------"+bankBusProd);
		if(StringUtils.isBlank(orderId)){
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1089);
		}
		if(StringUtils.isBlank(bankBusProd)){
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7014);
		}
	}

}